<template>
  <div class="code-gen">
    <el-form
      ref="genForm"
      class="gen-form"
      :model="clientParam"
      size="mini"
      label-width="150px"
    >
      <el-form-item
        label="选择数据源"
        prop="datasourceConfigId"
        :rules="{ required: true, message: '请选择数据源' }"
      >
        <el-select
          v-model="clientParam.datasourceConfigId"
          placeholder="选择数据源"
          @change="onDataSourceChange"
        >
          <el-option-group
            v-for="(datasourceConfigList, group) in datasourceGroupMap"
            :key="group"
            :label="group"
          >
            <el-option
              v-for="item in datasourceConfigList"
              :key="item.id"
              :label="getDatasourceLabel(item)"
              :value="item.id"
            >
              <span style="float: left">{{ getDatasourceLabel(item) }}</span>
              <span style="float: right; color: #8492a6; font-size: 13px">
                <el-tooltip placement="top" content="Duplicate">
                  <el-link
                    type="primary"
                    icon="el-icon-document-copy"
                    style="margin-right: 20px;"
                    @click.stop="onDataSourceDuplicate(item)"
                  ></el-link>
                </el-tooltip>
                <el-link
                  type="primary"
                  icon="el-icon-edit"
                  style="margin-right: 20px;"
                  @click.stop="onDataSourceUpdate(item)"
                ></el-link>
                <el-link
                  type="danger"
                  icon="el-icon-delete"
                  @click.stop="onDataSourceDelete(item)"
                ></el-link>
              </span>
            </el-option>
          </el-option-group>
        </el-select>
        <el-button type="text" @click="onDataSourceAdd">新建数据源</el-button>
      </el-form-item>
      <el-form-item v-show="showTable" label="包名（package）">
        <el-input
          v-model="clientParam.packageName"
          placeholder="可选，如：cn.studyjava.xxx"
          show-word-limit
          maxlength="100"
        />
      </el-form-item>
      <el-form-item v-show="showTable" label="模块名">
        <el-input
          v-model="clientParam.projectModule"
          placeholder="模块名"
          show-word-limit
          maxlength="100"
        />
      </el-form-item>
      <el-form-item v-show="showTable" label="删除前缀">
        <el-input
          v-model="clientParam.delPrefix"
          placeholder="可选，如：sys_user对应Java类为User(多前缀逗号隔开)"
          show-word-limit
          maxlength="100"
        />
      </el-form-item>
      <el-form-item v-show="showTable" label="作者名">
        <el-input
          v-model="clientParam.author"
          placeholder="可选，如：author"
          show-word-limit
          maxlength="100"
        />
      </el-form-item>
    </el-form>
    <el-row v-show="showTable" :gutter="20">
      <el-col :span="12">
        <h4>选择表</h4>
        <el-input
          v-model="tableSearch"
          prefix-icon="el-icon-search"
          clearable
          size="mini"
          placeholder="过滤表"
          style="margin-bottom: 10px;width: 100%;"
        />
        <el-table
          :data="tableListData"
          border
          :cell-style="cellStyleSmall()"
          :header-cell-style="headCellStyleSmall()"
          :row-class-name="tableRowClassName"
          @selection-change="onTableListSelect"
        >
          <el-table-column type="selection" />
          <el-table-column prop="tableName" label="表名" />
        </el-table>
      </el-col>
      <el-col :span="12" id="templateSelect">
        <h4>选择模板</h4>
        <el-select
          v-model="groupId"
          placeholder="选择模板所在组"
          @change="onTemplateGroupChange"
          size="mini"
          style="margin-bottom: 10px; width: 100%;"
        >
          <el-option
            v-for="item in groupData"
            :key="item.id"
            :label="item.groupName"
            :value="item.id"
          >
            {{ item.groupName }}
          </el-option>
        </el-select>
        <el-table
          ref="templateListSelect"
          :data="templateListData"
          border
          :cell-style="cellStyleSmall()"
          :header-cell-style="headCellStyleSmall()"
          :row-class-name="templateTableRowClassName"
          @selection-change="onTemplateListSelect"
        >
          <el-table-column type="selection" />
          <el-table-column prop="name" label="模板名称">
            <span slot-scope="scope">
              <!--              {{scope.row.groupName}}-{{scope.row.name}}-->
              {{ scope.row.name }}
            </span>
          </el-table-column>
        </el-table>
        <el-button v-show="showTable" type="primary" @click="onGenerate"
          >生成代码</el-button
        >
        <el-button
          v-show="showTable"
          type="primary"
          @click="onGenerate('_blank')"
          >生成代码(新窗口)</el-button
        >
      </el-col>
    </el-row>

    <el-dialog
      :title="datasourceTitle"
      :visible.sync="datasourceDlgShow"
      :close-on-press-escape="false"
      :close-on-click-modal="false"
    >
      <el-form
        ref="datasourceForm"
        :model="datasourceFormData"
        :rules="datasourceRule"
        size="mini"
        label-width="120px"
      >
        <el-form-item label="数据库分组" prop="dbGroupName">
          <el-input
            v-model="datasourceFormData.dbGroupName"
            placeholder="数据库分组名称(名称自定义，可重复)"
            show-word-limit
            maxlength="64"
          />
        </el-form-item>
        <el-form-item label="数据库类型">
          <el-select
            v-model="datasourceFormData.dbType"
            filterable
            default-first-option
          >
            <el-option
              v-for="item in dbTypeConfig"
              :key="item.dbType"
              :label="item.label"
              :value="item.dbType"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="数据库描述" prop="dbDesc">
          <el-input
            v-model="datasourceFormData.dbDesc"
            placeholder="数据库描述"
            show-word-limit
            maxlength="64"
          />
        </el-form-item>
        <el-form-item label="Host" prop="host">
          <el-input
            v-model="datasourceFormData.host"
            placeholder="地址"
            show-word-limit
            maxlength="100"
          />
        </el-form-item>
        <el-form-item label="Port" prop="port">
          <el-input
            v-model="datasourceFormData.port"
            placeholder="端口"
            show-word-limit
            maxlength="10"
          />
        </el-form-item>
        <el-form-item :label="dbNamePlaceholder" prop="dbName">
          <el-input
            v-model="datasourceFormData.dbName"
            :placeholder="dbNamePlaceholder"
            show-word-limit
            maxlength="64"
          />
        </el-form-item>
        <el-form-item label="连接类型" v-show="showOracleFields">
          <el-select v-model="datasourceFormData.oracleConnType">
            <el-option
              v-for="item in oracleConnTypeList"
              :key="item.val"
              :label="item.lab"
              :value="item.val"
            />
          </el-select>
        </el-form-item>
        <el-form-item
          v-show="showPgSqlSchema"
          :label="schemaPlaceholder"
          :prop="schemaPlaceholder"
        >
          <el-input
            v-model="datasourceFormData.schemaName"
            :placeholder="schemaPlaceholder + ',如SCOTT'"
            show-word-limit
            maxlength="64"
          />
        </el-form-item>
        <el-form-item label="Username" prop="username">
          <el-input
            v-model="datasourceFormData.username"
            placeholder="用户名"
            show-word-limit
            maxlength="100"
          />
        </el-form-item>
        <el-form-item label="角色" v-show="showOracleFields">
          <el-select v-model="datasourceFormData.oracleRole" clearable>
            <el-option
              v-for="item in oracleRoleList"
              :key="item.val"
              :label="item.lab"
              :value="item.val"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="Password" prop="password">
          <el-input
            v-model="datasourceFormData.password"
            type="password"
            placeholder="密码"
            show-word-limit
            maxlength="100"
          />
        </el-form-item>
        <el-form-item label="包名" prop="packageName">
          <el-input
            v-model="datasourceFormData.packageName"
            placeholder="包名（package）"
            show-word-limit
            maxlength="100"
          />
        </el-form-item>
        <el-form-item label="模块名" prop="projectModule">
          <el-input
            v-model="datasourceFormData.projectModule"
            placeholder="模块名"
            show-word-limit
            maxlength="100"
          />
        </el-form-item>
        <el-form-item label="删除前缀" prop="delPrefix">
          <el-input
            v-model="datasourceFormData.delPrefix"
            placeholder="删除前缀（表名sys_user删除前缀sys_对应bean为User）多前缀逗号隔开"
            show-word-limit
            maxlength="200"
          />
        </el-form-item>
        <el-form-item label="作者名" prop="author">
          <el-input
            v-model="datasourceFormData.author"
            placeholder="作者名"
            show-word-limit
            maxlength="100"
          />
        </el-form-item>
        <el-form-item label="代码生成器模板" prop="delPrefix">
          <el-select
            v-model="datasourceFormData.groupId"
            placeholder="选择模板所在组"
            size="mini"
            style="margin-bottom: 10px; width: 100%;"
          >
            <el-option
              v-for="item in groupData"
              :key="item.id"
              :label="item.groupName"
              :value="item.id"
            >
              {{ item.groupName }}
            </el-option>
          </el-select>
        </el-form-item>
        <el-form-item>
          <el-button type="success" @click="onDatasourceTest"
            >测试连接</el-button
          >
          <el-button type="primary" @click="onDatasourceSave">保存</el-button>
        </el-form-item>
      </el-form>
    </el-dialog>
  </div>
</template>
<style lang="scss">
.code-gen {
  margin: 0 auto;
  width: 70%;
  .el-input {
    width: 450px;
  }
  .el-row h4 {
    text-align: center;
  }
  .el-row .el-button {
    margin-top: 20px;
  }
}
.el-table .hidden-row {
  display: none;
}
#templateSelect {
  .el-input {
    width: 100%;
  }
}
</style>
<script>
const current_datasource_id_key = "gen-datasource-id";
const DB_TYPE = {
  MySQL: 1,
  Oracle: 2,
  SQL_Server: 3,
  PostgreSQL: 4,
  Dm: 5
};
export default {
  name: "GenerateConfig",
  data() {
    return {
      groupId: "",
      groupData: [],
      showTable: false,
      clientParam: {
        datasourceConfigId: "",
        tableNames: [],
        templateConfigIdList: [],
        packageName: "",
        projectModule: "",
        delPrefix: "",
        groupId: "",
        author: ""
      },
      tableSearch: "",
      datasourceGroupMap: {},
      datasourceConfigList: [],
      tableListData: [],
      templateListData: [],
      templateListSelect: [],
      // add datasource
      datasourceTitle: "新建连接",
      datasourceDlgShow: false,
      datasourceFormData: {
        id: 0,
        dbGroupName: "",
        dbType: 1,
        dbDesc: "",
        host: "",
        port: "",
        username: "",
        password: "",
        dbName: "",
        oracleConnType: "",
        oracleRole: "",
        schemaName: "",
        packageName: "",
        projectModule: "",
        delPrefix: "",
        groupId: "",
        author: ""
      },
      dbTypeConfig: [],
      oracleConnTypeList: [
        {
          lab: "服务名",
          val: 1
        },
        {
          lab: "SID",
          val: 2
        }
      ],
      oracleRoleList: [
        {
          lab: "default",
          val: ""
        },
        {
          lab: "SYSDBA",
          val: 1
        },
        {
          lab: "SYSOPER",
          val: 2
        }
      ],
      datasourceRule: {
        host: [{ required: true, message: "不能为空", trigger: "blur" }],
        port: [{ required: true, message: "不能为空", trigger: "blur" }],
        username: [{ required: true, message: "不能为空", trigger: "blur" }],
        password: [{ required: true, message: "不能为空", trigger: "blur" }],
        dbName: [{ required: true, message: "不能为空", trigger: "blur" }]
      }
    };
  },
  watch: {
    // 监听属性变化
    "clientParam.datasourceConfigId": function(id) {
      for (const item of this.datasourceConfigList) {
        if (item.id === id) {
          this.groupId = item.groupId;
          Object.assign(this.clientParam, {
            packageName: item.packageName,
            projectModule: item.projectModule,
            delPrefix: item.delPrefix,
            groupId: item.groupId,
            author: item.author
          });
          break;
        }
      }
    }
  },
  computed: {
    showPgSqlSchema() {
      return (
        this.datasourceFormData.dbType === DB_TYPE.PostgreSQL ||
        this.datasourceFormData.dbType === DB_TYPE.Oracle
      );
    },
    dbNamePlaceholder() {
      if (this.datasourceFormData.dbType === DB_TYPE.Oracle) {
        return "服务名";
      } else {
        return "数据库";
      }
    },
    schemaPlaceholder() {
      if (this.datasourceFormData.dbType === DB_TYPE.Oracle) {
        return "数据库";
      } else {
        return "schema";
      }
    },
    showOracleFields() {
      return this.datasourceFormData.dbType === DB_TYPE.Oracle;
    }
  },
  created() {
    this.loadDataSource();
    this.loadTemplate();
    this.loadDbType();
    this.loadGroups();
  },
  methods: {
    tableRowClassName: function({ row, index }) {
      // console.log("tablerow="+row.tableName+","+index)
      row.hidden = false;
      if (this.tableSearch.length === 0) {
        return "";
      }
      // console.log("tablerow="+row.tableName +","+ row.tableName.indexOf(this.tableName)+","+(!(row.tableName && row.tableName.indexOf(this.tableSearch) > -1)))
      if (
        !(
          row.tableName &&
          row.tableName.toLowerCase().indexOf(this.tableSearch.toLowerCase()) >
            -1
        )
      ) {
        row.hidden = true;
        return "hidden-row";
      }
      return "";
    },
    templateTableRowClassName: function({ row, index }) {
      // console.log("temprow="+row.id+",rowGroupId="+row.groupId+", this.groupId="+ this.groupId)
      row.hidden = false;
      if (this.groupId == "" || this.groupId <= 0) {
        return "";
      }
      // console.log("temprow="+row.groupId +","+(row.groupId && row.groupId == this.groupId))
      if (row.groupId && row.groupId == this.groupId) {
        return "";
      }
      row.hidden = true;
      return "hidden-row";
    },
    getDatasourceLabel(item) {
      const schema = item.schemaName ? `/${item.schemaName}` : "";
      const dbDesc = item.dbDesc ? item.dbDesc + "   " : "";
      return `${dbDesc}${item.dbName}${schema} (${item.host}) - ${
        item.username
      }`;
    },
    loadGroups() {
      this.post(`/group/list/`, {}, function(resp) {
        this.groupData = resp.data;
      });
    },
    loadDataSource() {
      const cacheId = this.getCurrentDataSourceId();
      this.post("/datasource/list", {}, resp => {
        let id;
        const list = resp.data;
        this.getDatasourceGroupMap(list);
        this.datasourceConfigList = list;
        for (const item of list) {
          // 缓存id是否有效
          if (item.id === cacheId) {
            id = item.id;
            break;
          }
        }
        if (!id && list.length > 0) {
          id = list[0].id;
        }
        if (id) {
          this.onDataSourceChange(parseInt(id));
        }
      });
    },
    getDatasourceGroupMap(list) {
      const groups = {};
      for (const item of list) {
        let groupName = item.dbGroupName || "";
        groups[groupName] = groups[groupName] || [];
        groups[groupName].push(item);
      }
      this.datasourceGroupMap = groups;
    },
    loadTemplate() {
      this.post("/template/list", {}, resp => {
        this.templateListData = resp.data;
      });
    },
    loadDbType() {
      this.post("/datasource/dbtype", {}, resp => {
        this.dbTypeConfig = resp.data;
      });
    },
    setCurrentDataSourceId(id) {
      this.setAttr(current_datasource_id_key, id);
    },
    getCurrentDataSourceId() {
      const id = this.getAttr(current_datasource_id_key);
      return parseInt(id) || "";
    },
    packageOracleFields() {
      // 处理oracle连接数据
      if (this.datasourceFormData.dbType === DB_TYPE.Oracle) {
        // 处理连接类型
        if (this.datasourceFormData.oracleConnType == 1) {
          this.datasourceFormData.dbName = "/" + this.datasourceFormData.dbName;
        } else if (this.datasourceFormData.oracleConnType == 2) {
          this.datasourceFormData.dbName = ":" + this.datasourceFormData.dbName;
        }
        // 处理账号角色
        if (this.datasourceFormData.oracleRole == 1) {
          this.datasourceFormData.username += " AS SYSDBA";
        } else if (this.datasourceFormData.oracleRole == 2) {
          this.datasourceFormData.username += " AS SYSOPER";
        }
      }
    },
    unPackOracleFields(item) {
      // 处理oracle属性 拆包
      if (item.dbType === DB_TYPE.Oracle) {
        // 处理连接类型
        if (item.dbName.startsWith("/")) {
          item.oracleConnType = 1;
          item.dbName = item.dbName.replace("/", "");
        } else if (item.dbName.startsWith(":")) {
          item.oracleConnType = 2;
          item.dbName = item.dbName.replace(":", "");
        }
        // 处理账号角色
        if (item.username.includes("AS SYSDBA")) {
          item.oracleRole = 1;
          item.username = item.username.replace(" AS SYSDBA", "");
        } else if (item.username.includes("AS SYSOPER")) {
          item.oracleRole = 2;
          item.username = item.username.replace(" AS SYSOPER", "");
        }
      }
    },
    onDataSourceAdd() {
      this.datasourceTitle = "新建连接";
      Object.keys(this.datasourceFormData).forEach(key => {
        this.datasourceFormData[key] = "";
      });
      this.datasourceFormData.id = 0;
      this.datasourceFormData.dbType = 1;
      this.datasourceDlgShow = true;
      this.$nextTick(() => {
        if (this.groupData.length > 0) {
          this.datasourceFormData.groupId = this.groupData[0].id;
        }
      });
    },
    onTemplateGroupChange(templateId) {
      //切换模板下拉框  清除先前被选中的模板
      this.$refs.templateListSelect.clearSelection();
    },
    onTableListSelect(selectedRows) {
      this.clientParam.tableNames = selectedRows
        .filter(row => row.hidden === undefined || row.hidden === false)
        .map(row => row.tableName);
    },
    onTemplateListSelect(selectedRows) {
      this.clientParam.templateConfigIdList = selectedRows
        .filter(row => row.hidden === undefined || row.hidden === false)
        .map(row => row.id);
    },
    onDataSourceChange(datasourceConfigId) {
      this.setCurrentDataSourceId(datasourceConfigId);
      this.clientParam.datasourceConfigId = datasourceConfigId;
      this.post(`/datasource/table/${datasourceConfigId}`, {}, resp => {
        this.showTable = true;
        this.tableListData = resp.data;
      });
    },
    onDataSourceUpdate(item) {
      this.datasourceTitle = "修改连接";
      this.unPackOracleFields(item);
      Object.assign(this.datasourceFormData, item);
      this.datasourceDlgShow = true;
    },
    onDataSourceDuplicate(item) {
      this.datasourceTitle = `${item.host} Copy`;
      Object.assign(this.datasourceFormData, item);
      this.datasourceFormData.id = 0;
      this.datasourceDlgShow = true;
    },
    onDataSourceDelete(row) {
      this.confirm(`确认要删除 ${row.dbName} 吗？`, function(done) {
        const data = {
          id: row.id
        };
        this.post("/datasource/del", data, function() {
          done();
          location.reload();
        });
      });
    },
    onGenerate(target) {
      this.$refs.genForm.validate(valid => {
        if (valid) {
          if (this.clientParam.tableNames.length === 0) {
            this.tip("请勾选表", "error");
            return;
          }
          if (this.clientParam.templateConfigIdList.length === 0) {
            this.tip("请勾选模板", "error");
            return;
          }
          const config = JSON.stringify(this.clientParam);
          console.log(target);
          if (target === "_blank") {
            //新窗口打开
            this.goRouteNewWindow(`result/${config}`);
          } else {
            this.goRoute(`result/${config}`);
          }
        }
      });
    },
    onDatasourceTest() {
      this.packageOracleFields();
      this.$refs.datasourceForm.validate(valid => {
        if (valid) {
          this.post(
            "/datasource/test",
            this.datasourceFormData,
            resp => {
              if (this.datasourceFormData.dbType === DB_TYPE.Oracle) {
                // 处理连接类型
                if (this.datasourceFormData.oracleConnType == 1) {
                  this.datasourceFormData.dbName = this.datasourceFormData.dbName.replace(
                    "/",
                    ""
                  );
                } else if (this.datasourceFormData.oracleConnType == 2) {
                  this.datasourceFormData.dbName = this.datasourceFormData.dbName.replace(
                    ":",
                    ""
                  );
                }
                // 处理账号角色
                if (this.datasourceFormData.oracleRole == 1) {
                  this.datasourceFormData.username = this.datasourceFormData.username.replace(
                    " AS SYSDBA",
                    ""
                  );
                } else {
                  this.datasourceFormData.username = this.datasourceFormData.username.replace(
                    " AS SYSOPER",
                    ""
                  );
                }
              }
              this.tip("连接成功");
            },
            err => {
              this.unPackOracleFields(this.datasourceFormData);
            }
          );
        }
      });
    },
    onDatasourceSave() {
      this.packageOracleFields();
      console.log("===>>>", this.datasourceFormData);
      this.$refs.datasourceForm.validate(valid => {
        if (valid) {
          this.post("/datasource/test", this.datasourceFormData, resp => {
            if (this.datasourceFormData.id) {
              this.post("/datasource/update", this.datasourceFormData, resp => {
                location.reload();
              });
            } else {
              this.post("/datasource/add", this.datasourceFormData, resp => {
                this.tip("添加成功");
                this.loadDataSource();
                this.datasourceDlgShow = false;
              });
            }
          });
        }
      });
    }
  }
};
</script>
